package tools

import (
	"errors"
	"github.com/golang-jwt/jwt/v4"
	"time"
)

/*func ParseToken(tokenString string, secret string) (int64, error) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method:%v", token.Header["alg"])
		}
		return []byte(secret), nil
	})
	if err != nil {
		return 0, err
	}
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		val := claims["userId"].(float64)
		exp := int64(claims["exp"].(float64))
		if exp <= time.Now().Unix() {
			return 0, errors.New("token过期了")
		}
		return int64(val), nil
	} else {
		return 0, err
	}
}*/

var mySigningKey = []byte("zhongxc.cc")

const TokenExpireDuration = time.Hour * 24

// MyClaims 自定义声明类型，并内嵌jwt.RegisteredClaims
// jwt包自带的jwt.RegisteredClaims只包含了官方字段
// 假设我们这里需要额外记录一个username字段，所以要自定义结构体
// 如果想要保存更多信息，都可以添加到这个结构体中
type MyClaims struct {
	Userid               int64  `json:"userid"`
	Username             string `json:"username"`
	jwt.RegisteredClaims        // 内嵌标准的声明
}

type AccessDetails struct {
	AccessUuid string
	UserId     int64
	Username   string
}

// GenRegisteredClaims 使用默认声明创建jwt
func GenRegisteredClaims() (string, error) {
	// 创建Claims
	claims := jwt.RegisteredClaims{
		ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)), // 过期时间
		Issuer:    "zhongxc",                                          // 签发人
	}
	// 生成token对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	// 生成签名字符串
	return token.SignedString(mySigningKey)
}

func ValidateRegisteredClaims(tokenString string) bool {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return mySigningKey, nil
	})
	// 解析token失败
	if err != nil {
		return false
	}
	return token.Valid
}

// GenToken 生成JWT Token
func GenToken(userId int64, userName string) (string, error) {
	claims := MyClaims{
		userId,
		userName,
		jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(TokenExpireDuration)),
			Issuer:    "zhongxc",
		},
	}
	// 使用指定的签名方法创建签名对象
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	// 使用指定的secret签名并获得完整的编码后的字符串token
	return token.SignedString(mySigningKey)
}

func ParseToken(tokenString string) (*AccessDetails, error) {
	// 解析token
	// 如果是自定义Claim结构体，则需要使用ParseWithClaims方法
	token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return mySigningKey, nil
	})
	if err != nil {
		return nil, err
	}
	// 对token对象中的claim进行类型断言
	if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
		return &AccessDetails{
			Username: claims.Username,
			UserId:   claims.Userid,
		}, nil
	}
	return nil, errors.New("invalid token")
}
